package com.wksc.workflow.dao;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.hql.internal.classic.QueryTranslatorImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

/**
 * Description:数据操作基类
 * Author: Zero
 * CreateTime: 2013-12-23 13:52
 */
public abstract class BaseHibernateDao<M extends Serializable, PKID extends Serializable> {
    protected Logger L = LoggerFactory.getLogger(getClass());

    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;

    protected Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    /**
     * 创建执行HQL语句Query对象
     *
     * @param hql HQL语句
     * @return Query对象
     */
    protected Query createHqlQuery(String hql) {
        return getSession().createQuery(hql);
    }

    /**
     * 创建执行SQL语句的Query对象
     *
     * @param sql SQL语句
     * @return SQLQuery对象
     */
    public SQLQuery createSqlQuery(String sql) {
        return getSession().createSQLQuery(sql);
    }

    @SuppressWarnings("unchecked")
    public PKID save(M model) {
        return (PKID) getSession().save(model);
    }

    public void update(M model) {
        getSession().update(model);
    }

    public void delete(Class cls, PKID id) {
        getSession().delete(get(cls, id));
    }

    public void deleteObject(M model) {
        getSession().delete(model);
    }

    public Object get(Class cls, PKID id) {
        return getSession().get(cls, id);
    }

    /**
     * 根据Hql语句和参数条件查询对应的记录
     *
     * @param hql    HQL语句
     * @param params 条件参数值
     * @param <T>    泛型对象
     * @return 泛型对象列表
     */
    @SuppressWarnings("unchecked")
    protected <T> List<T> list(String hql, Object... params) {
        Query query = createHqlQuery(hql);
        setParameters(query, params);
        return query.list();
    }

    /**
     * 根据Sql语句和参数条件查询对应的记录
     *
     * @param sql    SQL语句
     * @param cls    将记录转换成对应的实体对象，注：当cls值为null时将不进行转换
     * @param params 条件参数值
     * @param <T>    泛型对象
     * @return 泛型对象列表
     */
    @SuppressWarnings("unchecked")
    protected <T> List<T> list(String sql, Class cls, Object... params) {
        SQLQuery query = createSqlQuery(sql);
        setParameters(query, params);
        if (null != cls) {
            query.addEntity(cls);
        }
        return query.list();
    }

    /**
     * 根据HQL语句和查询条件，只返回唯一一条记录
     *
     * @param hql    HQL语句
     * @param params 条件参数值
     * @param <T>    泛型对象
     * @return 泛型对象
     */
    @SuppressWarnings("unchecked")
    protected <T> T uniqueResult(String hql, Object... params) {
        Query query = createHqlQuery(hql);
        setParameters(query, params);
        return (T) query.uniqueResult();
    }

    /**
     * 根据SQL语句和查询条件，只返回唯一一条记录
     *
     * @param sql    SQL语句
     * @param cls    将记录转换成对应的实体对象，注：当cls值为null时将不进行转换
     * @param params 条件参数值
     * @param <T>    泛型对象
     * @return 泛型对象
     */
    @SuppressWarnings("unchecked")
    protected <T> T uniqueResult(String sql, Class cls, Object... params) {
        SQLQuery query = createSqlQuery(sql);
        setParameters(query, params);
        if (null != cls) {
            query.addEntity(cls);
        }
        return (T) query.uniqueResult();
    }

    /**
     * 构造查询总记录数的SQL语句
     *
     * @param query
     * @return
     */
    private String getCountSql(Query query) {
        String sql = query.getQueryString();
        sql = "select count(*) from (" + hqlToSql(sql) + ") as tb_count";
        return sql;
    }

    /**
     * 将HQL语句转换成SQL语句
     *
     * @param hql HQL语句
     * @return SQL语句
     */
    protected String hqlToSql(String hql) {
        QueryTranslatorImpl queryTranslator = new QueryTranslatorImpl(
                hql,
                hql,
                Collections.EMPTY_MAP,
                (SessionFactoryImplementor) sessionFactory);

        queryTranslator.compile(Collections.EMPTY_MAP, false);
        return queryTranslator.getSQLString();
    }

    protected void setParameters(Query query, Object[] params) {
        if (null != params) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
    }

    protected void flush() {
        if (null != getSession()) {
            getSession().flush();
        }
    }

    protected void clear() {
        if (null != getSession()) {
            getSession().clear();
        }
    }

    protected void close() {
        if (null != getSession() && getSession().isOpen()) {
            getSession().close();
        }
    }

}
